#pragma once

#include<iostream>
#include<string>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>

using namespace std;
#define SIZE 128

class UdpServer{
public:
    UdpServer(int port)
    :_sockfd(-1),_port(port)
    {}
    void Init()
    {
        //创建socket文件描述符
        if((_sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1)
        {
            cout<<"socket error"<<endl;
            return;
        }
        cout<<"socket success"<<endl;

        //填入自己的套接字地址
        struct sockaddr_in local;
        memset(&local,0,sizeof(local));
        local.sin_family=AF_INET;
        local.sin_port=htons(_port);
        local.sin_addr.s_addr=htonl(INADDR_ANY);

        //绑定socket文件与套接字地址
        if(bind(_sockfd,(struct sockaddr*)(&local),sizeof(local))==-1)
        {
            cerr<<"bind error"<<endl;
            return;
        }
        cout<<"bind success"<<endl;

    }
    void Run()
    {
        char buffer[SIZE];  //buffer用来接收客户端传来的信息
        struct sockaddr_in peer;    //peer用来接收客户端的套接字地址信息
        socklen_t len=sizeof(peer);     //len用来接收套接字地址信息的长度

        while(true)
        {
            cout<<"测试"<<endl;
            //通过recvfrom函数从客户端接收数据和信息
            ssize_t size = recvfrom(_sockfd, buffer, sizeof(buffer)-1, 0, (struct sockaddr*)&peer, &len);
            //解析客户端的数据和信息
            
            if(size>=0)
            {
                buffer[size]='\n';
                int port=ntohs(peer.sin_port);
                string addr=inet_ntoa(peer.sin_addr);
                cout<<'['<<' '<<addr<<' '<<port<<' '<<"]: "<<buffer<<endl;
            }
            else
            {
                cerr<<"recvfrom error"<<endl;
                return;
            }
        }
    }
    ~UdpServer()
    {
        if(_sockfd>=0)
        {
            close(_sockfd);
        }
    }
private:
    int _sockfd;  //网络文件描述符
    int _port;    //服务器进程的端口号
};